#include "AudioEncoder.h"
#include "../include/proto.h"
#include <linux/soundcard.h>
#include "EncoderDevice.h"
#include "avcodec.h" 
typedef struct {
	enum CodecID codecID;
	BYTE wtwh_id;
}Codec_Map;

AudioEncoder::AudioEncoder(void){
	return;
};
AudioEncoder::~AudioEncoder(void){
	ACE_DEBUG((LM_DEBUG,"~AudioEncoder\n"));
	return;
};

int AudioEncoder::start()
{
	end_loop=FALSE;
	dsp_init();
	myAVcodec.sample_rate=audio_setting.sample_rate;
	myAVcodec.channels=audio_setting.channels;
	register_codec();
	avcodec_open(&myAVcodec, avcodec_find_encoder(audio_setting.codecID));
	audio_setting.frame_size=myAVcodec.frame_size * 2 * myAVcodec.channels;
	if (audio_setting.frame_size==2) audio_setting.frame_size=512;
	audio_buf=new BYTE[audio_setting.frame_size];
	audio_setting.audio_frame=audio_buf;
	activate();
	return 0;
}

int AudioEncoder::stop(void)
{
	end_loop=TRUE;
	while(end_loop) ACE_OS::sleep(ACE_Time_Value(0,10*1000));
	dsp_close();
	delete[] audio_buf;
	ACE_DEBUG((LM_DEBUG,"stop int AudioEncoder::end(void)\n"));
	return 0;
}
#include <sys/time.h>
int AudioEncoder::svc(void){
	FILE *fp;int dsp_out;
	fp=fopen("sound.dat","rb");
	BYTE *buf_out=new BYTE[audio_setting.frame_size];
	struct  timeval tv;
	struct timezone tz;

	dsp_out = ::open("/dev/dsp1", O_WRONLY);

	while(!end_loop){
		int iSize=::read(audio_fd, audio_buf, audio_setting.frame_size);
		iSize = avcodec_encode_audio(&myAVcodec, buf_out, audio_setting.frame_size, (short *)audio_buf);
//		printf ("size of %d\n",iSize);
//		fwrite(buf_out,iSize,1,fd);
//		fflush(fd);
//		iSize=512;
//		fread(buf_out,iSize,1,fp);
//		if (feof(fp)){
//			fseek(fp,0,SEEK_SET);printf ("set\n");
//		}
		write(dsp_out,audio_buf, audio_setting.frame_size);
		encoderDevice->sendData(iSize,buf_out,audio_setting.code_type,0);
	}
	delete[] buf_out;
	end_loop=FALSE;
	return 0;
}
int AudioEncoder::dsp_init(){
	int tmp,err;
	audio_fd = ::open(audio_setting.audio_dev, O_RDONLY);

	if (audio_fd < 0) {
		ACE_DEBUG((LM_ERROR,"audio_device %s open error\n",audio_setting.audio_dev));
		return -EIO;
	}


	/* select format : favour native format */
	err = ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &tmp);
	if (tmp & AFMT_S16_LE) {
		tmp = AFMT_S16_LE;
	} else if (tmp & AFMT_S16_BE) {
		tmp = AFMT_S16_BE;
	} else {
		tmp = 0;
	}

	err=ioctl(audio_fd, SNDCTL_DSP_SETFMT, &audio_setting.bitspersample);
	if (err < 0) {
		perror("SNDCTL_DSP_SETFMT");
		goto fail;
	}

	tmp = (audio_setting.channels == 2);
	printf ("tmp=%d\n",tmp);
	err = ioctl(audio_fd, SNDCTL_DSP_STEREO, &tmp);
	if (err < 0) {
		perror("SNDCTL_DSP_STEREO");
		goto fail;
	}

	err = ioctl(audio_fd, SNDCTL_DSP_SPEED, &audio_setting.sample_rate);
	if (err < 0) {
		perror("SNDCTL_DSP_SPEED");
		goto fail;
	}
	audio_setting.sample_rate = tmp; /* store real sample rate */
	return 0;
fail:
	close(audio_fd);
	return -EIO;

};
int AudioEncoder::dsp_close(){
	close(audio_fd);
	return 0;
};

void AudioEncoder::register_codec(){
#define PCM_CODEC(id, name) \
	register_avcodec(& name ## _encoder); \
	register_avcodec(& name ## _decoder); \
	
	PCM_CODEC(CODEC_ID_PCM_S16LE, pcm_s16le);
	PCM_CODEC(CODEC_ID_PCM_S16BE, pcm_s16be);
	PCM_CODEC(CODEC_ID_PCM_U16LE, pcm_u16le);
	PCM_CODEC(CODEC_ID_PCM_U16BE, pcm_u16be);
	PCM_CODEC(CODEC_ID_PCM_S8, pcm_s8);
	PCM_CODEC(CODEC_ID_PCM_U8, pcm_u8);
	PCM_CODEC(CODEC_ID_PCM_ALAW, pcm_alaw);
	PCM_CODEC(CODEC_ID_PCM_MULAW, pcm_mulaw);

	/* adpcm codecs */
	PCM_CODEC(CODEC_ID_ADPCM_IMA_QT, adpcm_ima_qt);
	PCM_CODEC(CODEC_ID_ADPCM_IMA_WAV, adpcm_ima_wav);
	PCM_CODEC(CODEC_ID_ADPCM_IMA_DK3, adpcm_ima_dk3);
	PCM_CODEC(CODEC_ID_ADPCM_IMA_DK4, adpcm_ima_dk4);
	PCM_CODEC(CODEC_ID_ADPCM_MS, adpcm_ms);
	PCM_CODEC(CODEC_ID_ADPCM_4XM, adpcm_4xm);
#undef PCM_CODEC
	return;
};
